package it.ictdays12.cipcip;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.twitterapime.rest.Credential;
import com.twitterapime.rest.FriendshipManager;
import com.twitterapime.rest.Timeline;
import com.twitterapime.rest.UserAccountManager;
import com.twitterapime.search.LimitExceededException;
import com.twitterapime.search.Query;
import com.twitterapime.search.QueryComposer;
import com.twitterapime.xauth.Token;

public class CipCipActivity extends Activity {
	
	// Consumer key values.
	public static final String CONSUMER_KEY = "ZqxD68cpr2wnbfEt2dAUlw";
	public static final String CONSUMER_SECRET = "nqUIWFfb7jlbs3BHzq4ZNoVykaJLnLWwpaPegyA6tBY";
	
	// Token key values.
	public static final String TOKEN_ACCESS = "433385722-zWDusIU4wnS7UPphakLqgUC9nrF2tzgAen4ikkQS";
	public static final String TOKEN_SECRET = "TPBFEMzejQyOOXWDBkHKYx3c8FzyxLTrkqaLp9W8RjE";
	
	// Number of tweet of the user's timeline to parse.
	public static final int tweetToParse = 10; 
	
	public ArrayList<Pair<String,String> > globalTagsInfo;
	public ArrayList<TagCounter> tagMatcher;
	public ArrayList<TagCounter> news;
	public ArrayList<TagCounter> newsList;
	
	// Number of user's following.
	public static int numFollowing = 0;
	
	// Semaphore value.
	public static int counter = 0;
	
	// Semaphore login for first refresh.
	public boolean logged = false;
	
	// Token, credentials and account manager.
	Token token;
	Credential c;
	UserAccountManager m;
	
	ArrayAdapter<TagCounter> adapter;
	ListView lv;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		globalTagsInfo	= new ArrayList<Pair<String,String> >();
		tagMatcher 		= new ArrayList<TagCounter>();
		news 			= new ArrayList<TagCounter>();
		
		// Link the ListView and the adapter.
		lv = (ListView) findViewById(R.id.newsListView);
		
		adapter = new TableRowAdapter(this, R.layout.row_layout, news);
		
        //adapter = new ArrayAdapter<TagCounter>(this, android.R.layout.simple_list_item_1, news);
        lv.setAdapter(adapter);
        
        /*lv.setOnItemClickListener(new OnItemClickListener() {
        	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        		TagCounter selectedTagCounter = news.get(position);
        		String linkNews = "https://www.google.it/search?hl=en&gl=it&tbm=nws&q=" + selectedTagCounter.hashtag; 
        		String linkTwitter = "https://twitter.com/#!/" + selectedTagCounter.hashtag;
        		Intent twitterIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkTwitter));
        		Intent gNewsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkNews));
        		startActivity(twitterIntent);
        	}
        });*/
        
        // Token.
		token 	= new Token(TOKEN_ACCESS, TOKEN_SECRET);
   	 	// Credential and user account manager.
		c 	= new Credential("DevisRossini", CONSUMER_KEY, CONSUMER_SECRET, token);
   	 	m 	= UserAccountManager.getInstance(c);
   	 	
   	 	// Login.
   	 	try {
   	 		if (m.verifyCredential()) {
   	 			Toast.makeText(CipCipActivity.this, "Login successful.", Toast.LENGTH_LONG).show();
   	 			logged = true;
			} else {
				Toast.makeText(CipCipActivity.this, "Login failed.", Toast.LENGTH_LONG).show();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (LimitExceededException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	protected void onStart() {
		super.onStart();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		while(logged == false);
		refresh();
	}
	
	// Create a simple menu for refresh the ListView.
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(Menu.NONE, 0, Menu.NONE, R.string.refresh);
		return true;
    }

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);
		refresh();
		return true;
	}
	
	// Load or refresh the ListView.
	private void refresh() {
		updateNumberFriend();
		updateTimeLine();
		matchTags();
		getNews();
	}
	
	// Update the number of following of the user.
	public void updateNumberFriend() {
		ProgressDialog dialog = new ProgressDialog(CipCipActivity.this);
		dialog.setMessage(getString(R.string.loading));
		dialog.show();
		
		FriendListReader.getFriendList(m);
		
		if(dialog.isShowing()) dialog.dismiss();
	}
	
	// Read user's timeline.
	public void updateTimeLine() {
		ProgressDialog dialog = new ProgressDialog(CipCipActivity.this);
		dialog.setMessage(getString(R.string.loading));
		dialog.show();
		
		TimeLineReader.getHomeTweet(m,globalTagsInfo);
		
		// Log pair's info.
		//		Iterator<Pair<String, String> > i = globalTagsInfo.iterator();
		//		while(i.hasNext()) {
		//			Log.d("Pair", i.next().toString());
		//		}
		
		if(dialog.isShowing()) dialog.dismiss();
	}
	
	// Parse tags and evalutate congruences.
	public void matchTags() {
		
		ArrayList<TagCounter> tagMatcher = new ArrayList<TagCounter>(); 
		boolean [] removed = new boolean[globalTagsInfo.size()];
		// Init the removed list.
		for(int i = 0; i < globalTagsInfo.size(); i++) 
			removed[i] = false;
		
		Iterator<Pair<String, String> > i = globalTagsInfo.iterator();
		while(i.hasNext()) {
			Pair<String,String> p = (Pair<String,String>)(i.next());
			
			if (removed[globalTagsInfo.indexOf(p)] == false) {
				removed[globalTagsInfo.indexOf(p)] = true;
				TagCounter tc = buildTagCounter(p);
			
				Iterator<Pair<String, String> > a = globalTagsInfo.iterator();
				while(a.hasNext()) {
					Pair<String,String> m = (Pair<String,String>)(a.next());
					if (removed[globalTagsInfo.indexOf(m)] == false) {
						TagCounter tmp = buildTagCounter(m);
						if (tmp.equals(tc)) {
							tc.counter += tmp.counter;
							removed[globalTagsInfo.indexOf(m)] = true;
						}
					}
				}
				// Add the tag counter.
				tagMatcher.add(tc);
			}
		}
		
		Iterator<TagCounter> it = tagMatcher.iterator();
		while(it.hasNext()) {
			TagCounter next = (TagCounter)it.next();
			double percent = ((double)((TagCounter)(next)).getCounter() / (double)numFollowing) * 100;
			//Log.d("Perc", String.valueOf(percent));
			next.setPercent(percent);
		}
		
		newsList = new ArrayList<TagCounter>();
		
		Iterator<TagCounter> n = tagMatcher.iterator();
		while(n.hasNext()) {
			TagCounter current = (TagCounter)n.next();
			double threshold = calculateThreshold(numFollowing);
			if(current.getCounter() > threshold)
				newsList.add(current);
		}
		
		TagCounterComparator comp = new TagCounterComparator();
		Collections.sort(newsList, comp);
	}	
	
	// Get news using the result of the match phase.
	public void getNews() {
		new GetNewsTask().execute();
	}
	
	// Helper function, creates a TagCounter from a pair's data.
	private TagCounter buildTagCounter(Pair<String,String> p) {
		String date = p.getLeft();
		String tag = p.getRight();
		long time = Long.valueOf(date);
		TagCounter tc = new TagCounter(tag,time);
		return tc;
	}
	
	private double calculateThreshold(int n) {
		if(n <= 12) return n / 100 * 5;
		else if(n >= 60) return n / 100 * (17 * n / 100) - 2;
		else if(n >= 90) return n / 100 * (8.7 - n / 100);
		else if(n >= 180) return n / 100 * (5 + 0.3 * n / 100);
		else return n / 100 * 5;
	}
	
	private static class FriendListReader {
		
		public static synchronized void getFriendList(UserAccountManager m) {
			FriendshipManager fsm = FriendshipManager.getInstance(m);
			try {
				String[] ids = fsm.getFriendsID(null); 
				numFollowing = ids.length;
			} catch (IOException e) {
				e.printStackTrace();
			} catch (LimitExceededException e) {
				e.printStackTrace();
			}
		}
	}
	
	private static class TimeLineReader {
		
		public static synchronized void getHomeTweet(UserAccountManager m, ArrayList<Pair<String,String>> tagsInfo) {
			Timeline tml = Timeline.getInstance(m);
			
			// Construct the query.
			Query q1 	= QueryComposer.includeEntities();
			Query q2 	= QueryComposer.count(tweetToParse);
			Query q 	= QueryComposer.append(q1, q2);
			
			// Reset the counter.
			counter = 0;
			
			tml.startGetHomeTweets(q, new CustomDeviceListener(tagsInfo));
			
			// Wait until all the thread have finished their work.
			while(counter != tweetToParse);
		}
	}
	
	private class GetNewsTask extends AsyncTask<String, Integer, Boolean> {
		
		ProgressDialog dialog = new ProgressDialog(CipCipActivity.this);
    	
		@Override
		protected void onPreExecute() {
			dialog.setMessage(getString(R.string.loading));
			dialog.show();
		}
		
		@Override
		protected Boolean doInBackground(String... params) {
			
			if(newsList.size() > 0) {
				news.clear();
				for (TagCounter oneNews : newsList) {
					news.add(oneNews);
					//Log.d("News", oneNews.toString());
				}
				
				/*String ns = Context.NOTIFICATION_SERVICE;
				NotificationManager mn = (NotificationManager) getSystemService(ns);
				
				int icon = R.drawable.default_image;
				CharSequence tickerText = "CipCip";
				long when = System.currentTimeMillis();
				
				Notification notification = new Notification(icon, tickerText, when);
				
				Context context = getApplicationContext();
				CharSequence contentTitle = "CipCip Notification";
				CharSequence contentText = "A news from your twitter friends. . .";
				Intent notificationIntent = new Intent(CipCipActivity.this, CipCipActivity.class);
				PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
				
				notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
				
				final int CIPCIP_ID = 1;
				
				mn.notify(CIPCIP_ID, notification);*/
				
				return true;
			}
			else
				return false;
		}
		
		@Override
		protected void onPostExecute(Boolean result) {
			if(dialog.isShowing()) dialog.dismiss();
			if(result) {
				adapter.notifyDataSetChanged();
			}
		}	
	}
}
